#include <iostream>
#include <string>
#include <memory>

// 建造者模式

// 抽象电脑类
class Computer
{
public:
    void setBoard(const std::string& board)
    {
        _board = board;
    }
    void setDisplay(const std::string& display)
    {
        _display = display;
    }
    virtual void setOs() = 0;
    void show()
    {
        std::string computer = "Computer:{\n";
        computer += "\tboard = " + _board + ",\n"; 
        computer += "\tdisplay = " + _display + ",\n"; 
        computer += "\tOs = " + _os + "\n"; 
        computer += "}\n";

        std::cout << computer << std::endl;
    }
protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

// 实现电脑类
class MacBook:public Computer
{
public:
    void setOs()override
    {
        _os = "Max Os X12";
    }
};

// 抽象建造者类
class Builder
{
public:
    virtual void buildBoard(const std::string& board) = 0;
    virtual void buildDisplay(const std::string& display) = 0;
    virtual void buildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 实现建造者类
class BuildMacBook:public Builder
{
public:
    // 使用指针一定要初始化
    BuildMacBook()
        :computer(new MacBook())
        {}
    void buildBoard(const std::string& board)override
    {
        computer->setBoard(board);
    }
    void buildDisplay(const std::string& display)override
    {
        computer->setDisplay(display);
    }
    void buildOs()override
    {
        computer->setOs();
    }
    std::shared_ptr<Computer> build()
    {
        return computer;
    }
protected:
    std::shared_ptr<Computer> computer;
};

// 实现指挥者
class Director
{
public:
    Director(std::shared_ptr<Builder> builder)
        :_builder(builder)
        {}
    void construct(const std::string& board,const std::string& display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOs();
    }
protected:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    std::shared_ptr<Builder> bulider(new BuildMacBook());
    std::unique_ptr<Director> director(new Director(bulider));
    director->construct("英特尔主板", "VOC显⽰器");
    std::shared_ptr<Computer> computer = bulider->build();
    computer->show();

    return 0;
}